home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-25 | 20.6 KB | 637 lines | [TEXT/CWIE] |
- //========================================================================================
- //
- // Generic EDL.c - A generic edit decision list export module.
- //
- // Written by Randy Ubillos and Bryan K. "Beaker" Ressler.
- //
- // Copyright ⌐ 1993-96, Adobe Systems Incorporated, all rights reserved worldwide.
- //
- // Version 1.00 10/20/93 Original version.
- // Version 1.01 9/12/95 Updated for 4.0.
- // Version 1.02 10/8/95 Updated for 4.2 and CW7.
- //
- // NOTE TO DEVELOPERS: This file contains a number of routines that are useful in the
- // parsing of Premiere's nested block EDL data structure. Not all the routines are
- // actually used by the Generic EDL -- they are provided in case you need them.
- //
- //========================================================================================
-
- //========================================================================================
- // Includes - use precompiled headers if compiling with CodeWarrior.
- //========================================================================================
- #ifdef __MWERKS__
- #ifdef powerc
- #include "PremierePPC"
- #else
- #include "Premiere68k"
- #endif
- #else
- #include "Premiere.h"
- #endif
-
- #include <stdarg.h>
-
- //========================================================================================
- // Constants
- //========================================================================================
- enum { // Resource IDs
- grStrings = 128, // STR# - standard file strings
- grKeyTypes = 129 // STR# - names of the key types
- };
-
- enum { // Strings in our STR# grStrings
- gsPrompt = 1,
- gsSuffix = 2
- };
-
- //========================================================================================
- // Static prototypes
- //========================================================================================
- static short WriteFile(short ref, Ptr data, long length);
- static short SendChar(short ref, char ch);
- static short WriteString(short ref, char *str);
- static short SendNum(short ref, long num);
- static short SendStr(short ref, char *fmt, ...);
- static short SendIndent(short ref, short amount);
- static short ParseBlock(BlockRec *theblock, short ref, short indent);
-
- //========================================================================================
- // Export module entry point
- //========================================================================================
- pascal short main (short selector, ExportHandle theData)
- {
- Str63 prompt, defaultName, suffix;
- StandardFileReply reply;
- short result = 0, err, ref;
-
- // Act according to the selector
- switch (selector) {
- case exExecute:
- // Get the standard put file prompt and the EDL filename suffix from our
- // string list. Append the suffix to the current project name.
- GetIndString(prompt, grStrings, gsPrompt);
- GetIndString(suffix, grStrings, gsSuffix);
- BlockMove((*theData)->projectName, defaultName,
- (*theData)->projectName[0] + 1);
- Append(defaultName, suffix);
-
- // Ask the user for an output filespec.
- StandardPutFile(prompt, defaultName, &reply);
- if (reply.sfGood) {
- // Delete any existing file with that name, then create and open a new
- // text file as specified by the user.
- FSpDelete(&reply.sfFile);
- // The following is ???? followed by TEXT
- err = FSpCreate(&reply.sfFile, 0x3f3f3f3f, 0x54455854, reply.sfScript);
- if (err == noErr)
- err = FSpOpenDF(&reply.sfFile, fsRdWrPerm, &ref);
-
- // Now call ParseBlock to parse the project and output an EDL to the
- // text file.
- if (err == noErr) {
- HLock((*theData)->dataHandle);
- ParseBlock((BlockRec *)*(*theData)->dataHandle, ref, 0);
- HUnlock((*theData)->dataHandle);
- FSClose(ref);
- MakeWindowForTextFile(&reply.sfFile);
- }
- }
- break;
-
- case exTrue30fps:
- // Return true here to get time values in 1/30 instead of 1/29.97.
- result = true;
- break;
- }
- return(result);
- }
-
- //========================================================================================
- // Write data to a file
- //========================================================================================
- static short WriteFile(short ref, Ptr data, long length)
- {
- long count;
-
- count = length;
- return(FSWrite(ref, &count, data));
- }
-
- //========================================================================================
- // Send a character to a file
- //========================================================================================
- static short SendChar(short ref, char ch)
- {
- return(WriteFile(ref, &ch, 1));
- }
-
- //========================================================================================
- // Send a string to a file
- //========================================================================================
- static short WriteString(short ref, char *str)
- {
- return(WriteFile(ref, str + 1, str[0]));
- }
-
- //========================================================================================
- // Send a number to a file
- //========================================================================================
- static short SendNum(short ref, long num)
- {
- Str127 str;
-
- NumToString(num, str);
- return(WriteString(ref, (char *)str));
- }
-
- //========================================================================================
- // Send a formatted string to a file. The parameter fmt is a format string akin to that
- // of printf (see table below)
- //
- // Specifier Parameter Description
- // ------------ ----------- ------------------------------------------------------------
- // %d long Substitute a long integer value output in decimal
- // %s char * Substitute a string
- // %t OSType Substitute an OSType value (output as a 4-character string)
- // %b char Substitute a byte value output in binary
- //========================================================================================
- static short SendStr(short ref, char *fmt, ...)
- {
- Str31 temp;
- va_list parm;
- long parms[kMaxExpandParms];
- char *where, *last, *start, oldChar;
- short param = 0, err = 0, i, num;
-
- // Unroll the parameters in advance (required for PowerPC)
- va_start(parm, fmt);
- for (i = 0; i < kMaxExpandParms; i++)
- parms[i] = va_arg(parm, long);
- va_end(parm);
-
- where = fmt + 1;
- last = fmt + fmt[0];
- while (err == noErr && (where <= last)) {
- start = where;
- if (where[0] == '%') {
- switch (where[1]) {
- case 'd': // %d means decimal
- err = SendNum(ref, parms[param++]);
- break;
- case 's': // %s means string
- err = WriteString(ref, (char *)parms[param++]);
- break;
- case 't': // %t means OSType
- temp[0] = 4;
- *((long*)(temp + 1)) = parms[param++];
- err = WriteString(ref, (char *)temp);
- break;
- case 'b': // %b means binary
- temp[0] = 8;
- num = parms[param++];
- for (i = 0; i <= 7; i++)
- temp[1 + i] = num & (0x0080 >> i) ? '1' : '0';
- err = WriteString(ref, (char *)temp);
- break;
- }
- where += 2;
- } else { // no substitution
- while ((where <= last) && (where[0] != '%'))
- where++;
- oldChar = start[-1];
- start[-1] = where - start;
- err = WriteString(ref, (char *)(start - 1));
- start[-1] = oldChar;
- }
- }
- return(err);
- }
-
- //========================================================================================
- // Send out spaces to do an indent
- //========================================================================================
- static short SendIndent(short ref, short amount)
- {
- short i, err = 0;
-
- for (i = 0; i < amount && err == noErr; i++)
- err = SendChar(ref, 9);
- return(err);
- }
-
- //========================================================================================
- // Take apart a block -- this routine is called recursively.
- //========================================================================================
- static short ParseBlock(BlockRec *theBlock, short ref, short indent)
- {
- short i, count, sValue, err = 0, mapping;
- long len, lValue;
- Rec_BLOK rBLOK;
- Rec_TREC rTREC;
- Rec_CLIP rCLIP;
- Rec_RPNT rRPNT;
- Rec_MREC rMREC;
- Rec_VIDI rVIDI;
- Rec_FXOP rFXOP;
- Rec_TIMB rTIMB;
- FSSpec rFILE;
- RGBColor theColor;
- Rect box;
- Point pt;
- Str31 str;
- Ptr pblock, p;
-
- // Indent and open this block
- err = SendIndent(ref, indent);
- if (err == noErr) err = SendChar(ref, '[');
-
- // Switch on all known types of block
- if (err == noErr) switch (theBlock->type) {
- case bBLOK:
- len = sizeof(Rec_BLOK);
- ExtractBlockData(theBlock, &rBLOK, &len);
- err = SendStr(ref, (char*)"\p'Adobe Premiere¬ 4.2 Generic Edit Decision List', Work_Start=%d, Work_End=%d",
- rBLOK.start, rBLOK.end);
- break;
- case bTRKB:
- err = SendStr(ref, (char*)"\pTracks", nil);
- break;
- case bTRAK:
- err = SendStr(ref, (char*)"\pTrack #%d", theBlock->theID);
- break;
- case bFVID:
- err = SendStr(ref, (char*)"\pVideo", nil);
- break;
- case bFSUP:
- err = SendStr(ref,(char*)"\pSuperImpose",nil);
- break;
- case bFAUD:
- err = SendStr(ref, (char*)"\pAudio", nil);
- break;
- case bAMAP:
- len = sizeof(mapping);
- ExtractBlockData(theBlock, &mapping, &len);
- err = SendStr(ref, (char*)"\pMapping=%b", mapping);
- break;
- case bFF_X:
- err = SendStr(ref, (char*)"\pFX", nil);
- break;
- case bTREC:
- len = sizeof(Rec_TREC);
- ExtractBlockData(theBlock, &rTREC, &len);
- err = SendStr(ref, (char*)"\pTrack_Record #%d, ClipID=%d, Start=%d, End=%d",
- theBlock->theID, rTREC.clipID, rTREC.start, rTREC.end);
- break;
- case bRBND:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pRubberBand, Max=%d", sValue);
- break;
- case bRPNT:
- len = sizeof(Rec_RPNT);
- ExtractBlockData(theBlock, &rRPNT, &len);
- err = SendStr(ref, (char*)"\pBand_Point #%d,h=%d,v=%d",
- theBlock->theID, rRPNT.h, rRPNT.v);
- break;
- case bFXOP:
- len = sizeof(Rec_FXOP);
- ExtractBlockData(theBlock, &rFXOP, &len);
- err = SendStr(ref, (char*)"\pFX_Options,Corners=%b,Direction=%d,Start=%d,End=%d",
- rFXOP.corners, rFXOP.direction, rFXOP.startPercent, rFXOP.endPercent);
- break;
- case bFXDF:
- len = sizeof(long);
- ExtractBlockData(theBlock, &lValue, &len);
- err = SendStr(ref, (char*)"\pFX_Type=%t", lValue);
- break;
- case bEDGE:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pEdge,Thickness=%d", sValue);
- break;
- case bMPNT:
- len = sizeof(Point);
- ExtractBlockData(theBlock, &pt, &len);
- err = SendStr(ref, (char*)"\pRef_Point,h=%d,v=%d",
- theBlock->theID, pt.h, pt.v);
- break;
- case bSPNT:
- len = sizeof(Point);
- ExtractBlockData(theBlock, &pt, &len);
- err = SendStr(ref, (char*)"\pStart_Point,h=%d,v=%d",
- theBlock->theID, pt.h, pt.v);
- break;
- case bEPNT:
- len = sizeof(Point);
- ExtractBlockData(theBlock, &pt, &len);
- err = SendStr(ref, (char*)"\pEnd_Point,h=%d,v=%d",
- theBlock->theID, pt.h, pt.v);
- break;
- case bOVER:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- GetIndString(str, 129, sValue+1);
- err = SendStr(ref, (char*)"\pOverlay, Type='%s'", (long)str);
- break;
- case bCOLR:
- len = sizeof(RGBColor);
- ExtractBlockData(theBlock, &theColor, &len);
- err = SendStr(ref, (char*)"\pColor,Red=%d,Green=%d,Blue=%d",
- theColor.red, theColor.green, theColor.blue);
- break;
- case bSIMI:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pSimilarity=%d", sValue);
- break;
- case bBLND:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pBlend=%d", sValue);
- break;
- case bTHRS:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pThreshold=%d", sValue);
- break;
- case bCUTO:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pCutoff=%d", sValue);
- break;
- case bALIA:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pAnti-Aliasing=%d", sValue);
- break;
- case bSHAD:
- err = SendStr(ref, (char*)"\pShadow", nil);
- break;
- case bRVRS:
- err = SendStr(ref, (char*)"\pKey_Reversed", nil);
- break;
- case bGARB:
- len = sizeof(Rect);
- ExtractBlockData(theBlock, &box, &len);
- err = SendStr(ref, (char*)"\pGarbage_Matte,Left=%d,Top=%d,Right=%d,Bottom=%d",
- box.left, box.top, box.right, box.bottom);
- break;
- case bPONT:
- len = sizeof(Point);
- ExtractBlockData(theBlock, &pt, &len);
- err = SendStr(ref, (char*)"\pPoint #%d,h=%d,v=%d", theBlock->theID, pt.h, pt.v);
- break;
- case bMATI:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pMatteID=%d", sValue);
- break;
- case bVFLT:
- err = SendStr(ref, (char*)"\pVideo_Filters", nil);
- break;
- case bAFLT:
- err = SendStr(ref, (char*)"\pAudio_Filters", nil);
- break;
- case bFILT:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pFileID=%d", sValue);
- break;
- case bMOTN:
- len = sizeof(Rect);
- ExtractBlockData(theBlock, &box, &len);
- err = SendStr(ref, (char*)"\pMotion,Left=%d,Top=%d,Right=%d,Bottom=%d",
- box.left, box.top, box.right, box.bottom);
- break;
- case bSMTH:
- err = SendStr(ref, (char*)"\pSmooth", nil);
- break;
- case bMREC:
- len = sizeof(Rec_MREC);
- ExtractBlockData(theBlock, &rMREC, &len);
- err = SendStr(ref, (char*)"\pMotion_Point #%d,Zoom=%d,Time=%d,Delay=%d,Rotation=%d,h=%d,v=%d",
- theBlock->theID, rMREC.zoom, rMREC.time, rMREC.delay, rMREC.rotation,
- rMREC.spot.h, rMREC.spot.v);
- break;
- case bDATA:
- err = SendStr(ref, (char*)"\pData #%d, %d bytes",
- theBlock->theID, theBlock->dataSize);
- break;
- case bCLPB:
- err = SendStr(ref, (char*)"\pClips", nil);
- break;
- case bCLIP:
- len = sizeof(Rec_CLIP);
- ExtractBlockData(theBlock, &rCLIP, &len);
- err = SendStr(ref, (char*)"\pClipID #%d,FileID=%d,In=%d,Out=%d",
- theBlock->theID, rCLIP.fileID, rCLIP.in, rCLIP.out);
- break;
- case bMARK:
- len = sizeof(long);
- ExtractBlockData(theBlock, &lValue, &len);
- err = SendStr(ref, (char*)"\pMark #%d, Location=%d", theBlock->theID, lValue);
- break;
- case bLOCK:
- err = SendStr(ref, (char*)"\pAspect_Locked", nil);
- break;
- case bRATE:
- len = sizeof(short);
- ExtractBlockData(theBlock, &sValue, &len);
- err = SendStr(ref, (char*)"\pRate=%d", sValue);
- break;
- case bFILB:
- err = SendStr(ref, (char*)"\pFiles", nil);
- break;
- case bFILE:
- err = SendStr(ref, (char*)"\pFileID #%d", theBlock->theID);
- break;
- case bMACS:
- len = sizeof(FSSpec);
- ExtractBlockData(theBlock, &rFILE, &len);
- err = SendStr(ref, (char*)"\pMac_Spec,Name='%s',vRefNum=%d,parID=%d",
- (long)rFILE.name, rFILE.vRefNum, rFILE.parID);
- break;
- case bMACP:
- len = 256;
- if (p = NewPtr(256)) {
- ExtractBlockData(theBlock, p, &len);
- err = SendStr(ref, (char*)"\pMac_Path='%s'", (long)p);
- DisposePtr(p);
- }
- break;
- case bFRMS:
- len = sizeof(long);
- ExtractBlockData(theBlock, &lValue, &len);
- err = SendStr(ref, (char*)"\pNum_Frames=%d", lValue);
- break;
- case bVIDI:
- len = sizeof(Rec_VIDI);
- ExtractBlockData(theBlock, &rVIDI, &len);
- err = SendStr(ref, (char*)"\pVideo,Width=%d,Height=%d,Depth=%d",
- rVIDI.frame.right, rVIDI.frame.bottom, rVIDI.depth);
- break;
- case bAUDI:
- len = sizeof(long);
- ExtractBlockData(theBlock, &lValue, &len);
- err = SendStr(ref, (char*)"\pAudio,Rate=%d", lValue);
- break;
- case bTIMC:
- if (pblock = NewPtr(256)) {
- len = 256;
- ExtractBlockData(theBlock, pblock, &len);
- err = SendStr(ref, (char*)"\pTimecode String='%s'", (long)pblock);
- DisposePtr(pblock);
- }
- break;
- case bTIMB:
- len = sizeof(Rec_TIMB);
- ExtractBlockData(theBlock, &rTIMB, &len);
- err = SendStr(ref, (char*)"\pTimecode Block,Frame=%d,DropFrame=%d,Format=%d",
- rTIMB.frames, rTIMB.dropframe, rTIMB.format);
- break;
- case bREEL:
- if (pblock = NewPtr(256)) {
- len = 256;
- ExtractBlockData(theBlock, pblock, &len);
- err = SendStr(ref, (char*)"\pReel_Name='%s'", (long)pblock);
- DisposePtr(pblock);
- }
- break;
- default:
- err = SendStr(ref, (char*)"\p'*** Unknown: '%t' #%d, %d bytes",
- theBlock->type, theBlock->theID, theBlock->dataSize);
- break;
- }
-
- // If there are any sub-blocks call ourselves recursively to parse them.
- if (err == noErr && theBlock->size > (sizeof(BlockRec) + theBlock->dataSize)) {
- err = SendChar(ref, ', ');
- if (!err) SendChar(ref, kReturn);
- count = CountTypeBlocks(-1, theBlock);
- for (i = 0; i < count && err == noErr; i++)
- err = ParseBlock(FindBlock(-1, -1, i, theBlock), ref, indent + 1);
- SendIndent(ref, indent);
- }
-
- // Close this block and a comma if we're not at level 0. End with a CR.
- if (err == noErr) err = SendChar(ref, ']');
- if (err == noErr && indent) err = SendChar(ref, ', ');
- if (err == noErr) err = SendChar(ref, kReturn);
- return(err);
- }
-
- //========================================================================================
- // Concatenate one data block onto the end of another, disposing the source handle
- //========================================================================================
- void AppendBlock(BlockRec **dstBlock, BlockRec **srcBlock)
- {
- HandAndHand((Handle)srcBlock, (Handle)dstBlock);
- DisposeHandle((Handle)srcBlock);
- }
-
- //========================================================================================
- // Add one data block into the end of another, disposing the source handle
- //========================================================================================
- void ExtendBlock(BlockRec **dstBlock, BlockRec **srcBlock)
- {
- HandAndHand((Handle)srcBlock, (Handle)dstBlock);
- (*dstBlock)->size += GetHandleSize((Handle)srcBlock);
- DisposeHandle((Handle)srcBlock);
- }
-
- //========================================================================================
- // Skip to the next block
- //========================================================================================
- void NextBlock(BlockRec **srcBlock)
- {
- *((Ptr*)srcBlock) += (*srcBlock)->size;
- }
-
- //========================================================================================
- // Count the number of blocks of a particular type. Pass -1 for type to count all types.
- //========================================================================================
- long CountTypeBlocks(long type, BlockRec *srcBlock)
- {
- long count;
- BlockRec *end, *pos;
-
- count = 0;
- end = (BlockRec *)(((Ptr)srcBlock) + srcBlock->size);
- pos = (BlockRec *)(((Ptr)srcBlock) + sizeof(BlockRec) + srcBlock->dataSize);
- while (pos < end) {
- if ((type == -1) || (pos->type == type))
- count++;
- NextBlock(&pos);
- }
- return(count);
- }
-
- //========================================================================================
- // Build a block of data with a header
- //========================================================================================
- BlockRec **BuildBlock(long type, long theID, long length, void *data)
- {
- BlockRec therec;
- Handle h;
-
- therec.size = length + sizeof(BlockRec);
- therec.dataSize = length;
- therec.type = type;
- therec.theID = theID;
- h = NewHandle(0);
- PtrAndHand((Ptr)&therec, h, sizeof(BlockRec));
- if (length != 0)
- PtrAndHand(data, h, length);
- return((BlockRec **)h);
- }
-
- //========================================================================================
- // Find a particular block. The parameters type, theID, or index may be -1 to indicate
- // that they are ignored.
- //========================================================================================
- BlockRec *FindBlock(long type, long theID, long index, BlockRec *srcBlock)
- {
- long count;
- BlockRec *end, *pos;
-
- count = 0;
- end = (BlockRec *)(((Ptr)srcBlock) + srcBlock->size);
- pos = (BlockRec *)(((Ptr)srcBlock) + sizeof(BlockRec) + srcBlock->dataSize);
- while (pos < end) {
- if ((index == count) && ((type == -1) || (pos->type == type)))
- return(pos);
- else if ((pos->type == type && pos->theID == theID))
- return(pos);
- if ((type == -1) || (pos->type == type))
- count++;
- NextBlock(&pos);
- }
- return(nil);
- }
-
- //========================================================================================
- // Return a handle to a numbered object
- //========================================================================================
- BlockRec **GetBlock(long type, long theID, long index, BlockRec **srcBlock)
- {
- BlockRec *destpos;
- Handle h;
-
- if (destpos = FindBlock(type, theID, index, *srcBlock)) {
- PtrToHand((Ptr)destpos, &h, destpos->size);
- return((BlockRec **)h);
- } else return(nil);
- }
-
- //========================================================================================
- // Copy the data from a numbered object
- //========================================================================================
- void ExtractBlockData(BlockRec *srcBlock, void *destination, long *maxlen)
- {
- long len;
-
- len = srcBlock->dataSize>*maxlen? *maxlen:srcBlock->dataSize;
- *maxlen = len;
- BlockMove(((Ptr)srcBlock)+sizeof(BlockRec), destination, len);
- }
-